﻿using System;
using System.IO;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

namespace JinndevEditor {

    public class CombineChannelEditor : EditorWindow {

        [MenuItem(CommonEditorConst.EditorMenu + "/合并纹理通道")]
        public static void Open() {
            var window = GetWindow<CombineChannelEditor>("合并纹理通道");
            window.Show();
        }

        private const int textureLength = 200;

        private Texture2D[] inputTextures = new Texture2D[4];
        private string[] inputNames = new string[] { "(R)", "(G)", "(B)", "(A)" };
        private ColorChannel[] inputChannels = new ColorChannel[] { ColorChannel.G, ColorChannel.G, ColorChannel.G, ColorChannel.G };
        private bool[] reverseChannels = new bool[] { false, false, false, false };

        private string[] outputTypes = new string[] { "TGA", "PNG" };
        private string outputType = "TGA";

        private Texture2D mainTexture;
        private Color defaultColor;

        private void OnGUI() {
            EditorGUILayout.Space(10);

            // 输入贴图
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.Space(10);
            mainTexture = DrawTexture("Input", mainTexture);
            EditorGUILayout.Space(50);
            for (int i = 0; i < inputTextures.Length; i++) {
                DrawInputTextures(i);
                EditorGUILayout.Space(20);
            }
            GUILayout.FlexibleSpace();
            EditorGUILayout.Space(10);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space(40);

            // 生成

            EditorGUILayout.BeginHorizontal();
            foreach (string type in outputTypes) {
                EditorGUILayout.LabelField(type, GUILayout.Width(30));
                if (EditorGUILayout.Toggle(outputType == type, GUILayout.Width(20))) {
                    outputType = type;
                }
            }
            if (mainTexture == null) {
                EditorGUILayout.Space(10, false);
                EditorGUILayout.LabelField("Default color", GUILayout.Width(80));
                defaultColor = EditorGUILayout.ColorField(defaultColor, GUILayout.Width(80));
            }
            EditorGUILayout.EndHorizontal();

            if (GUILayout.Button("生成", GUILayout.Width(100), GUILayout.Height(40))) {
                Generate();
            }

            EditorGUILayout.Space(10);
        }

        private Texture2D DrawTexture(string label, Texture2D texture2D) {
            EditorGUILayout.BeginVertical();
            
            texture2D = EditorGUILayout.ObjectField(texture2D, typeof(Texture2D), false, GUILayout.Width(textureLength), GUILayout.Height(textureLength)) as Texture2D;
            
            EditorGUILayout.LabelField(label, GUILayout.Width(textureLength));

            EditorGUILayout.EndVertical();
            return texture2D;
        }

        private void DrawInputTextures(int index) {
            EditorGUILayout.BeginVertical();

            // 输入纹理
            inputTextures[index] = EditorGUILayout.ObjectField(inputTextures[index], typeof(Texture2D), false, GUILayout.Width(textureLength), GUILayout.Height(textureLength)) as Texture2D;

            // 输入通道
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("In", GUILayout.Width(30));

            foreach (ColorChannel channel in Enum.GetValues(typeof(ColorChannel))) {
                EditorGUILayout.LabelField(channel.ToString(), GUILayout.Width(10));
                if (EditorGUILayout.Toggle(inputChannels[index] == channel, GUILayout.Width(20))) {
                    inputChannels[index] = channel;
                }
            }
            EditorGUILayout.EndHorizontal();

            // 输出通道
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Out " + inputNames[index], GUILayout.Width(62));
            EditorGUILayout.LabelField("Reverse", GUILayout.Width(50));
            reverseChannels[index] = EditorGUILayout.Toggle(reverseChannels[index], GUILayout.Width(20));
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.EndVertical();
        }

        private void Generate() {
            // 保存位置
            string name;
            string dir;
            if(mainTexture != null) {
                name = mainTexture.name + "_Combine";
                dir = CommonEditorUtil.GetDir(mainTexture);
            }
            else {
                name = "Combine";
                dir = CommonEditorUtil.GetDir(inputTextures);
            }

            string saveFile = EditorUtility.SaveFilePanel("选择保存位置", dir, name, outputType.ToLower());
            if (string.IsNullOrWhiteSpace(saveFile)) {
                return;
            }

            // 获取长宽
            int width = 0;
            int height = 0;
            if (mainTexture != null) {
                width = mainTexture.width;
                height = mainTexture.height;
            }

            for (int i = 0; i < inputTextures.Length; i++) {
                Texture2D inputTexture = inputTextures[i];
                if (inputTexture != null) {
                    if (width == 0) {
                        width = inputTexture.width;
                        height = inputTexture.height;
                    }
                    else if (width != inputTexture.width) {
                        Debug.LogError("输入纹理的长宽不一致");
                        return;
                    }
                }
            }

            // isReadable = true
            CommonEditorUtil.SetReadable(mainTexture, true);
            for (int i = 0; i < inputTextures.Length; i++) {
                CommonEditorUtil.SetReadable(inputTextures[i], true);
            }

            // SetPixels
            Texture2D outputTexture = new Texture2D(width, height);
            int step = 0;
            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    if (step++ % 256 == 0) {
                        EditorUtility.DisplayProgressBar("SetPixels", $"({x}, {y})", (float)(y * width + x) / (width * height));
                    }
                    Color outputColor = mainTexture == null ? defaultColor : mainTexture.GetPixel(x, y);
                    CommonEditorUtil.SetPixel(inputTextures[0], x, y, inputChannels[0], ColorChannel.R, reverseChannels[0], ref outputColor);
                    CommonEditorUtil.SetPixel(inputTextures[1], x, y, inputChannels[1], ColorChannel.G, reverseChannels[1], ref outputColor);
                    CommonEditorUtil.SetPixel(inputTextures[2], x, y, inputChannels[2], ColorChannel.B, reverseChannels[2], ref outputColor);
                    CommonEditorUtil.SetPixel(inputTextures[3], x, y, inputChannels[3], ColorChannel.A, reverseChannels[3], ref outputColor);
                    outputTexture.SetPixel(x, y, outputColor);
                }
            }

            // isReadable = false
            CommonEditorUtil.SetReadable(mainTexture, false);
            for (int i = 0; i < inputTextures.Length; i++) {
                CommonEditorUtil.SetReadable(inputTextures[i], false);
            }

            // Save output
            byte[] bytes;
            if (outputType == "TGA") {
                bytes = outputTexture.EncodeToTGA();
            }
            else {
                bytes = outputTexture.EncodeToPNG();
            }
            DestroyImmediate(outputTexture);

            File.WriteAllBytes(saveFile, bytes);
            AssetDatabase.Refresh();
            EditorUtility.ClearProgressBar();
        }


    }
}
